<?php

namespace app\common\model;


class Base62 {
    const STANDARD_BASE = 256;
    const TARGET_BASE = 62;

    private static $GMP_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    private static $INVERTED_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    private $alphabet;
    private $lookup = [];

    // 获取GMP风格实例
    public static function getInstance() {
        static $instance = null;
        if (!$instance) {
            $instance = new self(str_split(self::$GMP_CHARS));
        }
        return $instance;
    }

    // 获取倒序字符集实例
    public static function getInvertedInstance() {
        static $instance = null;
        if (!$instance) {
            $instance = new self(str_split(self::$INVERTED_CHARS));
        }
        return $instance;
    }

    private function __construct($alphabet) {
        $this->alphabet = $alphabet;
        $this->createLookupTable();
    }

    // 编码方法
    public function encode($input) {
        $message = array_values(unpack('C*', $input));
        $converted = $this->convert($message, self::STANDARD_BASE, self::TARGET_BASE);
        return $this->translate($converted, $this->alphabet);
    }

    // 解码方法
    public function decode($encoded) {
        if (!$this->isBase62($encoded)) {
            throw new InvalidArgumentException("Invalid Base62 string");
        }

        $bytes = array_map(function($c) { return ord($c); }, str_split($encoded));
        $prepared = $this->translate($bytes, $this->lookup);
        $converted = $this->convert($prepared, self::TARGET_BASE, self::STANDARD_BASE);
        return pack('C*', ...$converted);
    }

    // 验证Base62字符串
    private function isBase62($str) {
        return preg_match('/^[a-zA-Z0-9]+$/', $str);
    }

    // 核心转换逻辑
    private function convert($message, $sourceBase, $targetBase) {
        $out = [];
        $source = $message;

        while (!empty($source)) {
            $quotient = [];
            $remainder = 0;

            foreach ($source as $byte) {
                $accumulator = $byte + $remainder * $sourceBase;
                $digit = intval($accumulator / $targetBase);
                $remainder = $accumulator % $targetBase;

                if (!empty($quotient) || $digit > 0) {
                    $quotient[] = $digit;
                }
            }

            array_unshift($out, $remainder);
            $source = $quotient;
        }

        // 处理前导零
        for ($i = 0; $i < count($message) - 1 && $message[$i] == 0; $i++) {
            array_unshift($out, 0);
        }

        return $out;
    }

    // 字符映射
    private function translate($indices, $dictionary) {
        $result = '';
        foreach ($indices as $index) {
            $result .= $dictionary[$index];
        }
        return $result;
    }

    // 创建查找表
    private function createLookupTable() {
        $this->lookup = array_flip($this->alphabet);
    }
}